package com.chigga.common.utils;

import com.auth0.jwt.JWT;
import com.auth0.jwt.algorithms.Algorithm;
import com.auth0.jwt.exceptions.JWTVerificationException;
import com.auth0.jwt.interfaces.DecodedJWT;
import com.chigga.common.config.properties.JwtProperties;
import jakarta.annotation.Resource;
import org.springframework.stereotype.Component;

import java.util.Date;
import java.util.Map;

/**
 * JWT 工具类
 *
 * @author DefChigga
 */
@Component
public class JwtUtil {

    @Resource
    private JwtProperties jwtProperties;
    
    private static final String CLAIM_NAME = "userInfo";

    /**
     * 获取签名算法
     *
     * @return 签名算法
     */
    private Algorithm getSign() {
        // 生成 HMAC256 算法加密后的密钥 / 加盐
        return Algorithm.HMAC256(jwtProperties.getSecret());
    }

    /**
     * 创建 JWT 令牌
     *
     * @param username 用户名
     * @return JWT令牌
     */
    public String createToken(String username) {
        return JWT.create()
                // 设置主题
                .withSubject(username)
                // 设置签发者
                .withIssuer(jwtProperties.getIssuer())
                // 设置签发时间
                .withIssuedAt(new Date())
                // 设置过期时间
                .withExpiresAt(new Date(System.currentTimeMillis() + jwtProperties.getExpires() * 1000))
                // 使用 HMAC256 算法签名
                .sign(getSign());
    }

    /**
     * 创建 JWT 令牌
     *
     * @param claim 用户信息
     * @return JWT令牌
     */
    public String createToken(Map<String, Object> claim) {
        return JWT.create()
                // 设置用户信息
                .withClaim(CLAIM_NAME, claim)
                // 设置主题
                .withSubject(jwtProperties.getSubject())
                // 设置签发者
                .withIssuer(jwtProperties.getIssuer())
                // 设置签发时间
                .withIssuedAt(new Date())
                // 设置过期时间
                .withExpiresAt(new Date(System.currentTimeMillis() + jwtProperties.getExpires() * 1000))
                // 使用 HMAC256 算法签名
                .sign(getSign());
    }

    /**
     * 验证 JWT 令牌
     *
     * @param token JWT令牌
     */
    public void verifyToken(String token) throws JWTVerificationException {
        // 使用 HMAC256 算法验证
        JWT.require(getSign())
                // 设置签发者
                .withIssuer(jwtProperties.getIssuer())
                // 创建验证器
                .build()
                // 验证令牌
                .verify(token);
    }

    /**
     * 获取主题
     *
     * @param token JWT令牌
     * @return 主题
     */
    public String getSubject(String token) {
        DecodedJWT decodedJwt = JWT.decode(token);
        return decodedJwt.getSubject();
    }

    /**
     * 获取用户信息
     *
     * @param token JWT令牌
     * @return 用户信息
     */
    public Map<String, Object> getUserInfo(String token) {
        DecodedJWT decodedJwt = JWT.decode(token);
        return decodedJwt.getClaim(CLAIM_NAME).asMap();
    }

    /**
     * 获取用户名
     *
     * @param token JWT令牌
     * @return 用户名
     */
    public String getUsername(String token) {
        DecodedJWT decodedJwt = JWT.decode(token);
        return (String) decodedJwt.getClaim(CLAIM_NAME).asMap().get("username");
    }

    /**
     * 获取用户ID
     *
     * @param token JWT令牌
     * @return 用户ID
     */
    public Integer getUserId(String token) {
        DecodedJWT decodedJwt = JWT.decode(token);
        return (Integer) decodedJwt.getClaim(CLAIM_NAME).asMap().get("userId");
    }

    /**
     * 获取用户信息 Map 值
     *
     * @param token JWT令牌
     * @param key Map key
     * @return 用户ID
     */
    public Object getUserValue(String token, String key) {
        DecodedJWT decodedJwt = JWT.decode(token);
        return decodedJwt.getClaim(CLAIM_NAME).asMap().get(key);
    }
}